package org.elsfs.cloud.common.mybatis.ext.sql;

import com.baomidou.mybatisplus.core.metadata.OrderItem;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;


import java.util.Collection;

/**
 * 查询条件
 *
 * @param <C> 子类具体类型
 * @param <H> Having条件构建器类型
 */
@SuppressWarnings("unchecked")
public interface SelectCondition<C extends SelectCondition<C, H>, H extends SelectCondition.HavingConditionBuilder<H, C>> extends SortableCondition<C> {

    /**
     * 分组
     *
     * @param fields 分组字段名称
     * @return 具体实现
     */
    C groupBy(String... fields);

    /**
     * 分组
     *
     * @param fields 分组字段枚举
     * @return 具体实现
     */
    C groupBy(Enum<?>... fields);

    /**
     * 分组
     *
     * @param fields 分组字段名称
     * @return 具体实现
     */
    C groupBy(Collection<String> fields);

    /**
     * 分组
     *
     * @param fields 分组字段枚举
     * @return 具体实现
     */
    C groupByEnum(Collection<Enum<?>> fields);

    /**
     * 设置分组条件
     *
     * @return 条件构建器
     */
    HavingConditionBuilder<H, C> having();

    /**
     * 偏移数量
     *
     * @param number 数量
     * @return 具体实现
     */
    C offset(long number);

    /**
     * 分组
     *
     * @param condition 条件
     * @param fields 分组字段名称
     * @return 具体实现
     */
    default C groupBy(boolean condition, String... fields) {
        if (condition) {
            return this.groupBy(fields);
        }

        return (C) this;
    }

    /**
     * 分组
     *
     * @param condition 条件
     * @param fields 分组字段枚举
     * @return 具体实现
     */
    default C groupBy(boolean condition, Enum<?>... fields) {
        if (condition) {
            return this.groupBy(fields);
        }

        return (C) this;
    }

    /**
     * 分组
     *
     * @param condition 条件
     * @param fields 分组字段名称
     * @return 具体实现
     */
    default C groupBy(boolean condition, Collection<String> fields) {
        if (condition) {
            return this.groupBy(fields);
        }

        return (C) this;
    }

    /**
     * 分组
     *
     * @param condition 条件
     * @param fields 分组字段枚举
     * @return 具体实现
     */
    default C groupByEnum(boolean condition, Collection<Enum<?>> fields) {
        if (condition) {
            return this.groupByEnum(fields);
        }

        return (C) this;
    }

    /**
     * 偏移数量
     *
     * @param condition 条件
     * @param number 数量
     * @return 具体实现
     */
    default C offset(boolean condition, long number) {
        if (condition) {
            return this.offset(number);
        }

        return (C) this;
    }

    /**
     * 分页处理
     *
     * @param page 页码
     * @param size 分页大小
     * @return 具体实现
     */
    default C paginate(long page, long size) {
        return this.limit(size)
            .offset(
                (page - 1) * size
            );
    }

    /**
     * 分页处理
     *
     * @param page 分页对象
     * @return 具体实现
     */
    default C paginate(Page<?> page) {
        for (OrderItem order : page.orders()) {
            this.orderBy(order.isAsc(), order.getColumn());
        }

        return this.limit(page.getSize())
            .offset(
                (page.getCurrent() - 1) * page.getSize()
            );
    }

    /**
     * 分组条件接口
     *
     * @param <C> 具体实现
     * @param <P> 父容器类具体实现
     */
    interface HavingConditionBuilder<C extends HavingConditionBuilder<C, P>, P extends SelectCondition<P, C>> extends Condition<C>, Completable<P> {
    }
}
